Repository navigation
fix(remote): attribute remote-driven turns to the session's owning workspace - #3894
Merged
bobleer merged 4 commits intoNov 12, 2026
Merged
Conversation
…rkspace
A turn started from a phone or bot on a persisted session that the desktop
had not loaded created a "Remote Session" placeholder bound to whichever
workspace was current. Every later save, delete, archive and activity read
for that session was then refused by the host ("Session ID is already bound
to another workspace"), so the row showed the syncing icon forever and could
be neither deleted nor archived.
- DialogTurnStarted carries the session's workspace binding (optional, absent
from older hosts) and the frontend projects it with the same keys as
session-created, so the placeholder lands in its owning workspace.
- A placeholder for an already persisted session hydrates its earlier turns
on open, adopts the host's title, mode and binding when its metadata
arrives, and never writes its guessed title over the persisted name. A
placeholder created earlier without a binding (image analysis) is rebound
when the turn start names the owner.
- A full metadata checkpoint is skipped when the stored record cannot be
read, instead of resetting tags and title facts.
- Delivered approvals take priority over the syncing state; the status mark
shows its label on hover.
- Delete, archive, rename and copy failures use localized copy and explain a
workspace binding mismatch instead of showing raw host text.
An image-analysis start can project a session before its creation event arrives. The creation event now rebinds that placeholder to the owning workspace and adopts the host record, instead of being ignored.
A relay frame missing a field, or a presence list in an unexpected shape, ended the host's relay loop for good: no disconnect event, no reconnect, and the host stayed unreachable from phones and bots until restart. Drop and log such frames; stop only on a newer connection epoch or a closed event receiver.
…ion-workspace-binding # Conflicts: # src/web-ui/src/flow_chat/services/flow-chat-manager/EventHandlerModule.test.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
A HarmonyOS phone (Remote Connect) started a turn on a persisted desktop session that the desktop Web UI had not loaded.
agentic://dialog-turn-startedcarried no workspace facts, sohandleDialogTurnStartedcreated a "Remote Session" placeholder bound to the current workspace (the personal assistant workspace), while the host stored the session under its project workspace. From then on:delete_sessionandarchive_sessionwas refused withSession ID is already bound to another workspace;Seen in a user's diagnostics on 1.0.10 (Windows); no earlier fix in history.
Fix
Contract / backend
AgenticEvent::DialogTurnStartedgains an optionalsession_binding: SessionWorkspaceBinding(#[serde(default)], omitted whenNone). The coordinator fills it at every emit site from the loaded session's config without cloning the session.workspacePath,projectWorkspacePath,executionTarget,workspaceId,remoteConnectionId,remoteSshHost— the same keyssession-createdalready uses, so the existing resolver attributes the placeholder correctly.Web UI
externalPlaceholder. For a persisted session (turnIndex > 0) the placeholder startsmetadata-only, so opening it hydrates earlier turns; it then adopts the host's title, mode and binding as soon as its metadata is read, keeping the live turns it already projected.sessionName/titleMetadata) over the persisted record. Without this, a correct binding would have let the first remote turn rename the real session to "Remote Session".Related fixes found while reviewing remote-control robustness
session-creatednow corrects a placeholder that an earlier event (image analysis) projected before it, instead of being ignored.Compatibility
session_binding; the payload is unchanged and the frontend keeps its previous fallback. Covered by a legacy-payload deserialization test.Remote scenarios
Testing
AI-assisted; lightly tested (focused automated tests, no manual run against a device).
cargo test -p openbitfun-events --lib dialog_turn_startedcargo test -p openbitfun-core --no-default-features --features agent-runtime,git --lib user_shell_command_persists_a_standard_exec_command_tool_turncargo check --tests -p openbitfun-core -p openbitfun-agent-runtime -p openbitfun-services-integrations -p openbitfun-clicargo test -p openbitfun-services-integrations --no-default-features --features remote-connect --lib relay_clientpnpm --dir src/web-ui run test:runforEventHandlerModule,FlowChatStore,PersistenceModule,SessionModule,sessionNavStatus,sessionMutationFailureandNavPanel/sections/sessionspnpm run i18n:audit,pnpm run type-check:web